import isotp
from crc import Configuration
import struct
import udsoncan
from udsoncan import DataIdentifier
from ctypes import *

# dll1 = cdll.LoadLibrary('SeednKey.dll')

CRCconfig = Configuration(
    width=32,
    polynomial=0x04C11DB7,
    init_value=0xFFFFFFFF,
    final_xor_value=0xFFFFFFFF,
    reverse_input=True,
    reverse_output=True,
)
RX_ID = 0x77B
TX_ID_PHYS = 0x773
TX_ID_FUNC = 0x7DF


def myalgo(level, seed, params):
    Mask = 0
    if level == 0x01:
        Mask = params[0]
    elif level == 0x11:
        Mask = params[1]
    key = 0
    if seed != 0:
        temp_key = (seed[0] << 24) | (seed[1] << 16) | (seed[2] << 8) | (seed[3])
        for i in range(35):
            if temp_key & 0x80000000:
                temp_key = temp_key << 1
                temp_key = temp_key ^ Mask
            else:
                temp_key = temp_key << 1
        key = temp_key
    output_key = struct.pack('BBBB', (key >> 24) & 0xFF, (key >> 16) & 0xFF,
                             (key >> 8) & 0xFF, key & 0xFF)
    return output_key


isotp_params = {
    'stmin': 20,
    # 将请求发送方在连续帧之间等待时间。0 ~ 127ms或100 ~ 900ns，取值范围为0xf1 ~ 0xf9
    # Will request the sender to wait 32ms between consecutive frame. 0-127ms or 100-900ns with values from 0xF1-0xF9
    'blocksize': 8,
    # 流控帧单包大小,0为不限制
    # Request the sender to send 8 consecutives frames before sending a new flow control message
    'wftmax': 5,
    # 错误帧最大数
    # Number of wait frame allowed before triggering an error
    'tx_data_length': 8,
    # 数据链路层数据长度
    # Link layer (CAN layer) works with 8 byte payload (CAN 2.0)
    'tx_data_min_length': None,
    # 数据链路层最小长度, 当不为None时, 将填充字节
    # Minimum length of CAN messages. When different from None, messages are padded to meet this length. Works with CAN 2.0 and CAN FD.
    'tx_padding': 0,
    # 空白字节用0x00填充
    # Will pad all transmitted CAN messages with byte 0x00.
    'rx_flowcontrol_timeout': 1000,
    # 流控帧超时时间
    # Triggers a timeout if a flow control is awaited for more than 1000 milliseconds
    'rx_consecutive_frame_timeout': 1000,
    # 连续帧超时时间
    # Triggers a timeout if a consecutive frame is awaited for more than 1000 milliseconds
    'squash_stmin_requirement': False,
    # 发送方尽可能快的发送
    # When sending, respect the stmin requirement of the receiver. If set to True, go as fast as possible.
    'max_frame_size': 4095
    # 接收帧的大小
    # Limit the size of receive frame.
}
client_config = {
    'exception_on_negative_response': True,  # 否定响应错误使能
    'exception_on_invalid_response': True,  # 无效响应错误使能
    'exception_on_unexpected_response': True,  # 未知响应错误使能
    'security_algo': myalgo,  # 安全访问函数
    'security_algo_params': [0xa7a5e4e3, 0x1C47E825],  # 安全访问参数
    'tolerate_zero_padding': True,
    'ignore_all_zero_dtc': True,
    'dtc_snapshot_did_size': 2,
    # dtc快照的did大小
    # Not specified in standard. 2 bytes matches other services format.
    'server_address_format': None,  # 8,16,24,32,40
    'server_memorysize_forma': None,  # 8,16,24,32,40
    'data_identifiers':
        {
            DataIdentifier.BootSoftwareIdentification: udsoncan.DidCodec("cccccccc"),
            DataIdentifier.ActiveDiagnosticSession: udsoncan.DidCodec("c"),
            DataIdentifier.VehicleManufacturerSparePartNumber: udsoncan.DidCodec("ccccccccc"),
            DataIdentifier.VehicleManufacturerECUSoftwareNumber: udsoncan.DidCodec("ccccccccccccccccc"),
            DataIdentifier.SystemSupplierIdentifier: udsoncan.DidCodec("cccccccccc"),
            DataIdentifier.ECUManufacturingDate: udsoncan.DidCodec("cccc"),
            DataIdentifier.ECUSerialNumber: udsoncan.DidCodec("cccccccccccccccccccc"),
            DataIdentifier.VIN: udsoncan.DidCodec("BBBBBBBBBBBBBBBBB"),
            DataIdentifier.SystemSupplierECUHardwareVersionNumber: udsoncan.DidCodec("cccccccc"),  # ASCII
            DataIdentifier.SystemSupplierECUSoftwareVersionNumber: udsoncan.DidCodec("cccccccc"),
            0xF012: udsoncan.DidCodec("BBBBBBBBB"),
            #   字符          c类型             py类型            标准大小
            #   x           填充字节            无对应值            []
            #   c           char            长度为1的bytes          1
            #   b           signed char         integer           1
            #   B           unsigned char       integer           1
            #   ?           _Bool               bool              1
            #
        },
    'input_output': {},
    'request_timeout': 5,
    'p2_timeout': 1,
    'p2_star_timeout': 5,
    'standard_version': 2020,  # 2006, 2013, 2020
    'use_server_timing': False
}

tp_physaddr = isotp.Address(isotp.AddressingMode.Normal_11bits, txid=TX_ID_PHYS,
                            rxid=RX_ID)  # Network layer addressing scheme
tp_funcaddr = isotp.Address(isotp.AddressingMode.Normal_11bits, txid=TX_ID_FUNC,
                            rxid=RX_ID)  # Network layer addressing scheme
